home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1984,1985 Omen Technology Inc All Rights Reserved
- * Ward Christensen Protocol handler for sending and receiving
- * ascii and binary files. Modified for choice of checksum or crc.
- * This code may be used for developing YMODEM support ONLY IF
- * the program documentation acknowledges the origin of this code.
- */
-
- #ifdef CPM
- EXT char defdisk; /* Default disk */
- EXT char origdisk; /* Disk originally logged into */
- #define PSTRLEN 33 /* For misc string params */
- #ifndef PATHLEN
- #define PATHLEN 65 /* Plenty long */
- #endif
- #endif
-
- #define CTRL(v) ('v' & 037)
- #define ERROR (-1)
- #define BACKUP (-3) /* Returned to expand to access prev file */
- #define NOTFOUND (-4) /* Returned to expand to indicate can't open */
- #define FOUNDIT (-5) /* Function found what it was looking for */
- #define OK 0
- #define TRUE 1
- #define FALSE 0
- #define SAYTERM 2 /* Doykbd returns this if sayterm needed */
- #define SECSIZ 128
- #define CPMEOF 0x1A
-
- /*
- * Some important usage() error numbers
- */
- #define SJ_ABORT 20 /* Keyboard abort via abort key */
-
- EXT FILE *cfin, /* Surrogate input getcty, kgets */
- *fin, /* For file uploads */
- *fout, /* For file downloads */
- *cout, /* For text capture and utility command redirection */
- *fcall; /* script reader */
-
- EXT char cfast; /* BDS C fastest access is to extern's */
- EXT char checksum; /* Delcared here for speed */
- EXT unsigned oldcrc; /* Accumulates CRC checksum */
- EXT int wcj, firstch, errors;
- EXT int firstsec; /* First sector, C instead of NAK for crc */
-
- #define CMDLEN 130
-
- #define SOH 1
- #define STX 2
- #define ETX 3
- #define EOT 4
- #define ENQ 5
- #define ACK 6
- #define SO 016
- #define SI 017
- #define DLE 020
- #define XON 021
- #define XOFF 023
- #define NAK 025
- #define CAN 030
- #define ESC 033
- #define WANTCRC 0103 /* Send C not NAK to get crc not checksum */
- #define WANTG 0107 /* Send G not NAK to get nonstop batch xmsn */
- #define TIMEOUT (-2)
- #define WAICHR '\336' /* Causes a wait in put[w] and answerback */
- #define RETRYMAX 10
- #define RETRYNOCRC 4 /* Drop CRC request after 4 retries */
- #define KSIZE 1024 /* Block length with k option */
-
- /* Declare all globally used functions not returning int */
- char *index(), *cisubstr(), *stem();
- char *ascgettime(), *ascgetd(), *ascexpftime();
- char **gettoken();
- long fseek(), toutime(), time();
- unsigned updetime();
- FILE *xfopen();
-
- This code has been modified from the Professional-YAM code with
- EXT unsigned Etime; /* Elapsed time in seconds */
- EXT struct tsruct calltime; /* Set when connection is made */
- EXT int Zone; /* Zone in minutes from GMT */
- EXT int Thiszone; /* Timezone to use for this command */
-
- /*
- * Structure passed by e1xpand to called function.
- * most just use the first string part (sorry, lint!)
- */
- #define UFNSIZE 68 /* 64 byte pathlen plus drive */
- #define FNLENGTH 15 /* Directory filename */
- #define DONOMATCH 0x8000 /* Always expand pathspecs */
- struct expf {
- char expfname[UFNSIZE]; /* ASCIZ file name */
- long expflen; /* File length in bytes */
- unsigned exptime;
- unsigned expdate;
- char expfn[FNLENGTH]; /* Filename only no path */
- char expfattr; /* File attribute */
- };
-
-
- EXT char Cname[PATHLEN], Rname[PATHLEN], Tname[PATHLEN]; /* Saved filenames */
-
- #define MAXPACK 94 /* Maximum Kermit packet size */
- #define RBUFL 200 /* Kermit Receive buffer length */
-
- /* Some declarations for USQ feature */
- #define SQMAGIC 0xFF76 /* SQueezed file prefix */
- #define KSQMAGIC 0xFF75 /* Cipher key magic word */
- #define KEYSIZE 4096 /* Max size of key file */
- #define NUMVALS 257 /* 256 data values plus SPEOF*/
-
- extern union { /* Decoding tree for usq feature */
- struct {
- char ffxpkt[MAXPACK+8]; /* Far fetch MUST BE FIRST */
- char rxpkt[RBUFL+2]; /* Receive packet buffer */
- char txpkt[MAXPACK+8]; /* Packet buffer */
- char sxpkt[MAXPACK+8]; /* Server command buffer */
- char dxpkt[MAXPACK+8]; /* Packet buffer */
- char axbuf[CMDLEN+2]; /* For CB command, etc. */
- char kfilnam[PATHLEN+2];
- } k;
- char ubuf[KSIZE+2];
- struct {
- int children[2]; /* Left, Right */
- } dnode[NUMVALS - 1];
- } U;
-
- EXT FLAG Key; /* True iff unsqueezing encrypted file */
-
-
-
- expanations added for support routines not included.
-
- #include "yamsys.h" /* Installation specific stuff */
- #include "yam.h"
- #define WCEOT (-10)
-
- long Modtime; /* Unix style mod time for incoming file */
- int Usemtime; /* <>0: Accept file mod time */
- int Filemode; /* Unix style mode for incoming file */
- char rxcmdchar; /* NAK, C, or G to specify rx mode */
- extern char *Rcmdlog; /* Remote commands logged to this file */
- static FLAG eotseen; /* <>0 if an EOT has been seen for this rx packet */
-
- wcsend(argc, argp)
- char **argp;
- {
- int wcs();
-
- Crcflg = FALSE;
- firstsec = TRUE;
- if (Batch) {
- lhmargin();
- printf("Sending in Batch Mode\n");
- /* Expand calls the specified function once for each file, with that
- pathname as argument */
- if (expand(wcs, argc, argp, 0) == ERROR)
- goto fubar;
- if (wctxpn("") == ERROR)
- goto fubar;
- }
- else {
- for (; --argc>=0;) {
- /* Opentx opens a file for sending - `ala fopen(name, "rb" .. */
- if (opentx(*argp++) == ERROR)
- goto fubar;
- if (wctx() == ERROR)
- goto fubar;
- }
- }
- return OK;
- fubar:
- closetx('E'); ++Errcnt;
- canit();
- return ERROR;
- }
-
- wcs(ufn)
- register struct expf *ufn;
- {
- if (opentx(ufn->expfname) == ERROR)
- return OK; /* skip over inaccessible files */
- if (wctxpn(ufn) == ERROR)
- return ERROR;
- if (wctx() == ERROR)
- return ERROR;
- return OK;
- }
-
-
- wcreceive(argc, argp)
- char **argp;
- {
- rxcmdchar = NAK;
- if (Batch || argc == 0)
- Crcflg = Batch = TRUE;
- if (Crcflg)
- rxcmdchar = WANTCRC;
- if (Optiong > 0)
- Crcflg = rxcmdchar = WANTG;
-
- if (Batch) {
- lhmargin(); Batch = TRUE;
- printf("Receiving in Batch Mode\n");
- if (argc)
- usage(11);
- for (;;) {
- if (wcrxpn(U.ubuf)== ERROR)
- goto fubar;
- if (U.ubuf[0] == 0) {
- pstat(""); return OK;
- }
- procheader(U.ubuf);
-
- if (wcrx(U.ubuf) == ERROR)
- goto fubar;
- }
- }
- else {
- procheader(NULL);
- if (Xmodem)
- printf("Receive:'%s' FILE OPEN\n", *argp);
- if (wcrx(*argp) == ERROR)
- goto fubar;
- }
- Bytesleft = DEFBYTL; return OK;
- fubar:
- Bytesleft = DEFBYTL; canit(); closerx(eotseen?'Q':ERROR);
- ++Errcnt; return ERROR;
- }
-
- /*
- * Fetch a pathname from the other end as a C ctyle ASCIZ string.
- * Length is indeterminate as long as less than blklen
- * a null string represents no more files
- */
- wcrxpn(rpn)
- char *rpn; /* receive a pathname */
- {
- purgeline();
- Crcflg = firstsec = TRUE;
- lpstat("Fetching pathname");
- totsecs = -1;
- if (wcgetsec(rpn, rxcmdchar) != 0)
- return ERROR;
- /* Send the ACK unless g option */
- if (Optiong <= 0)
- sendline(ACK);
- FLUSHMO;
- return OK;
- }
-
- wctxpn(ufn)
- struct expf *ufn;
- {
- register char *p, *q;
- int i;
- #ifdef MTIME
- long mdt; struct dstruct d; struct tsruct t;
- #endif
- totsecs = -1;
- pstat("Awaiting pathname NAK");
- if (getnak())
- return ERROR;
- for (i = KSIZE, q = U.ubuf; --i >= 0; )
- *q++ = 0;
- p = ufn->expfname;
- if (*p) {
- #ifdef MTIME
- tdexpftime(&d, &t, ufn);
- mdt = toutime(&d, &t) + Thiszone*60L;
- #endif
- if (!Fullpath) {
- p = stem(p);
- uncaps(p);
- }
- for(q = U.ubuf; *p; ) /* don't send drive: */
- if((*q++ = *p++) == ':')
- q = U.ubuf;
- /* transmit file length */
- #ifdef MTIME
- sprintf(++q, "%ld %lo 0 %ld", ufn->expflen, mdt, Serialn);
- #else
- sprintf(++q, "%ld 0 0 %ld", ufn->expflen, Serialn);
- #endif
- }
-
- if (wcputsec(U.ubuf, 0, SECSIZ) == ERROR) {
- wcperr("Can't send pathname %s", p);
- return ERROR;
- }
- return OK;
- }
-
- getnak()
- {
- register c;
-
- Lastrx = 0;
- for (;;) {
- FLUSHMO;
- switch (firstch = readline(400)) {
- case TIMEOUT:
- return TRUE;
- case WANTG:
- Optiong = 1; blklen = 1024;
- /* **** FALL THRU TO **** */
- case WANTCRC:
- Crcflg = TRUE;
- /* **** FALL THRU TO **** */
- case NAK:
- if ((c=readl0()) == TIMEOUT)
- return FALSE;
- if (c == 'K') { /* IMP hack */
- blklen = 1024; return FALSE;
- }
- /* **** FALL THRU TO **** */
- case CAN:
- if (Lastrx == CAN)
- return TRUE;
- /* **** FALL THRU TO **** */
- default:
- showctl(firstch);
- }
- Lastrx = firstch;
- }
- }
-
- /*
- * Adapted from CMODEM13.C, written by
- * Jack M. Wierda and Roderick W. Hart
- */
-
- wcrx(name)
- char *name;
- {
- register char *p;
- register cblklen; /* bytes to dump this block */
- int sendchar, sectnum, sectcurr;
- int syntry; /* number of tries to get right sec */
-
- if (openrx(name) == ERROR)
- return ERROR;
- firstsec = TRUE; eotseen = FALSE; totsecs = sectnum = 0;
- sendchar = rxcmdchar;
-
- for (;;) {
- syntry = 0; /* # of tries for right sector */
- synagain:
- sectcurr = wcgetsec(U.ubuf, sendchar);
- if (sectcurr == (sectnum+1 & 0377)) {
- sectnum++;
- /*
- * if the compiler supports longs && the o/s records the
- * exact length of files then and only then use the file length
- * info (if transmitted).
- */
- wcj = cblklen = Bytesleft>blklen ? blklen:Bytesleft;
-
- Charsrx += wcj;
- if (Overlapio) {
- if (Optiong <= 0)
- sendline(ACK);
- sendchar = -1;
- } else
- sendchar=ACK;
- FLUSHMO;
- for (p = U.ubuf; --wcj>=0; )
- if (putc(*p++, fout) == ERROR)
- usage(30);
- if (View) {
- wcj = cblklen;
- for (p = U.ubuf;--wcj>=0;)
- bttyout(*p++);
- }
- if ((Bytesleft -= cblklen) < 0)
- Bytesleft = 0;
- totsecs += blklen/128;
- }
- else if (sectcurr == (sectnum & 0377)) {
- wcperr("Received dup Sector");
- sendchar = ACK;
- }
- else if (sectcurr == WCEOT) {
- sendline(ACK);
- FLUSHMO;
- /* Don't pad the file any more than it already is */
- closerx('R');
- #ifdef MTIME
- if (Modtime) {
- sutime(Rname, Modtime - Thiszone*60L);
- Modtime = 0L;
- }
- #endif
- return OK;
- }
- else if (sectcurr == ERROR)
- return ERROR;
- else {
- wcperr("Sync Error: got %d", sectcurr);
- if (++syntry < 12) {
- sendchar = Batch ? WANTCRC : NAK;
- goto synagain;
- }
- return ERROR;
- }
- }
- }
-
- /*
- * wcgetsec fetches a Ward Christensen type sector.
- * Returns:
- * sector number encountered
- * or ERROR if valid sector not received, or CAN CAN received
- * or WCEOT if eot sector
- ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
- * (Caller must do that when he is good and ready to get next sector)
- */
-
- wcgetsec(rxbuf, sendchar)
- char *rxbuf;
- {
- register char *p;
- register c;
- register sectcurr;
- register maxtim = 100;
-
- eotseen = FALSE;
- for (Lastrx = errors = 0; errors < RETRYMAX; ++errors, ++toterrs) {
- if(Ctrlbrk)
- return ERROR;
-
- if (firstsec && !Batch && errors >= RETRYNOCRC ) {
- sendchar = NAK; Crcflg = FALSE;
- }
- showsec();
- if (sendchar > 0) {
- sendline(sendchar); /* Send it now, we're ready! */
- }
- FLUSHMO;
- blklen = SECSIZ;
- noisereject:
- switch (c = readline(maxtim)) {
- case CAN:
- if (Lastrx == CAN) {
- wcperr("Sender CANcelled");
- return ERROR;
- } else {
- Lastrx = CAN;
- continue;
- }
- case EOT:
- if (Optiong)
- return WCEOT;
- ++eotseen;
- /* make sure eot really is eot and not just mixmash */
- if (readl0() == TIMEOUT) {
- if (!Crcflg || Lastrx == EOT)
- return WCEOT;
- Lastrx = EOT; goto bilge3;
- }
- goto bilge;
- case STX:
- blklen = KSIZE;
- case SOH:
- sectcurr = readline(50);
- if ((sectcurr+readline(50)) == 0377) {
- checksum = oldcrc = 0;
- for (p = rxbuf,wcj = blklen; --wcj>=0; ) {
- if ((c = readline(50)) < 0)
- goto bilge;
- oldcrc = updcrc(c, oldcrc);
- checksum += (*p++ = c);
- }
- if ((c = readline(50)) < 0)
- goto bilge;
- if (Crcflg) {
- oldcrc = updcrc(c, oldcrc);
- if ((c = readline(50)) < 0)
- goto bilge;
- oldcrc = updcrc(c, oldcrc);
- if (oldcrc) {
- wcperr("Bad CRC=%04x",
- oldcrc);
- goto bilge2;
- }
- else {
- firstsec = FALSE;
- return sectcurr;
- }
- }
- else if ((checksum-c) & 0377) {
- wcperr("Checksum Bad rx=%02x cx=%02x",
- c, checksum);
- goto bilge2;
- } else {
- firstsec = FALSE;
- return sectcurr;
- }
- }
- wcperr("Sector number garbled"); goto bilge;
- default:
- if (Crcflg)
- goto noisereject;
- case TIMEOUT:
- break;
- }
- bilge:
- switch (c) {
- case TIMEOUT:
- wcperr("Timeout"); goto bilge3;
- case ERROR: case (ERROR & ~0200):
- Mcstat = 0;
- wcperr("Modem SR=%02x", Mcstat);
- break;
- default:
- wcperr("Got %02x sector header", c);
- break;
- }
- bilge2:
- junkpacket();
- bilge3:
- if (firstsec)
- sendchar = rxcmdchar;
- else {
- maxtim = 50;
- sendchar = NAK;
- }
- }
- /* try to stop the bubble machine. */
- canit(); return ERROR;
- }
-
- /*VARARGS1*/
- wcperr(s,p,q)
- char *s, *p, *q;
- {
- char bufx[70];
-
- llhmargin();
- sprintf(bufx, s, p, q);
- lprintf("Sector %3d error %d: %s\n", totsecs, errors, bufx);
- #ifdef DEBUG2
- if ( !Serialn) {
- logfile(Rcmdlog, bufx, firstch, (long)totsecs);
- if (Xmodem && !carrier())
- logfile(Rcmdlog, "CARRIER LOST", 'C', (long)updetime());
- }
- #endif
- }
-
- showsec()
- {
- if (!Quiet)
- pstat("Sector %3d %2dk %s",
- totsecs, totsecs/8, Crcflg?"CRC-16":"" );
- }
-
- wctx()
- {
- register char *p;
- register unsigned sectnum;
-
- firstsec = TRUE; totsecs = 0;
- pstat("Awaiting initial NAK");
-
- if (getnak())
- return ERROR;
- sectnum = 1;
- while (filbuf(U.ubuf, blklen)) {
- totsecs += (blklen/128);
- showsec();
- if (wcputsec(U.ubuf, sectnum, blklen) == ERROR) {
- #ifdef DEBUG2
- if ( !Serialn)
- logfile(Rcmdlog, "SE1", firstch, Charstx);
- #endif
- if (firstch == WANTCRC && sectnum > 1) {
- long lseek();
-
- if (lseek(fileno(fin), -blklen*2L, 1) == -1L)
- return ERROR;
- --sectnum; Charstx -= blklen;
- totsecs -= (blklen/64);
- wcperr("Resynchronizing");
- continue;
- }
- return ERROR;
- } else {
- if (View)
- for (p = U.ubuf,wcj = blklen;--wcj>=0;)
- bttyout(*p++);
- ++sectnum; Charstx += blklen;
- }
- }
- closetx('S');
- for (errors = 0; ++errors<RETRYMAX; ) {
- purgeline();
- sendline(EOT);
- FLUSHMO;
- if (Ctrlbrk)
- break;
- if((firstch=readline(100)) == ACK || firstch == (ACK|0200))
- return OK;
- wcperr("Got %02x for ACK to EOT", firstch);
- }
- wcperr("No ACK on EOT");
- return ERROR;
- }
-
- wcputsec(txbuf, sectnum, cseclen)
- char *txbuf;
- register unsigned sectnum;
- int cseclen; /* data length of this sector to send */
- {
- register char *p;
- FLAG nogood;
-
- firstch = 0; /* part of logic to detect CAN CAN */
-
- for (errors = 0; errors < RETRYMAX; ++errors, ++toterrs) {
- nogood = FALSE;
- if (Ctrlbrk)
- goto cancan;
- Lastrx = firstch;
- sendline(cseclen == KSIZE?STX:SOH);
- sendline(sectnum);
- sendline(-sectnum-1);
- oldcrc = checksum = 0;
- for (wcj = cseclen,p = txbuf; --wcj>=0; ) {
- sendline(*p);
- oldcrc = updcrc(*p, oldcrc);
- checksum += *p++;
- if (miinqueue()) {
- switch (michar()) {
- case CAN:
- goto chkcan;
- case XOFF:
- readline(500); break;
- default:
- break;
- }
- }
- }
- if (Crcflg) {
- oldcrc = updcrc(0,updcrc(0,oldcrc));
- sendline(oldcrc>>8);sendline(oldcrc);
- }
- else
- sendline(checksum);
- if (Ctrlbrk)
- goto cancan;
-
- if (miready()) {
- wcperr("Noise Burst Detected");
- if (Optiong > 0)
- goto cancan;
- nogood = TRUE; purgeline();
- }
- if (Optiong) {
- firstsec = FALSE; return OK;
- }
- FLUSHMO;
- firstch = readline(400);
- gotnak:
- switch (firstch) {
- case CAN:
- chkcan:
- if(Lastrx == CAN) {
- cancan:
- wcperr("Receiver Cancelled"); return ERROR;
- }
- break;
- case TIMEOUT:
- wcperr("Timeout on sector ACK"); continue;
- case WANTCRC:
- if (firstsec)
- Crcflg = TRUE;
- case NAK:
- wcperr("NAK on sector");
- #ifdef NOTDEF
- /* ******* TESTING ********** */
- {
- extern Quitafter;
- if (Quitafter && Verbose) {
- wcperr("Faking ACK: ALT-Q");
- Quitafter = FALSE; return OK;
- }
- }
- #endif
- continue;
- case ACK:
- gotack:
- if (nogood)
- break;
- if (!Tfile || (sectnum==0) || (readl0()==TIMEOUT)) {
- firstsec = FALSE; return OK;
- }
- wcperr("Got burst for sector ACK");
- break;
- case ACK|0200:
- if ( !Tfile)
- goto gotack;
- default:
- wcperr("Got %02x for sector ACK", firstch); break;
- }
- for (;;) {
- Mcstat = 0;
- Lastrx = firstch;
- if ((firstch = readline(400)) == TIMEOUT)
- break;
- if ((firstch == NAK || firstch == WANTCRC)
- && readl0() == TIMEOUT)
- goto gotnak;
- if (firstch == CAN && Lastrx == CAN)
- goto cancan;
- /* Let user see it if strange char */
- showctl(firstch);
- }
- }
- wcperr("No ACK on sector");
- return ERROR;
- }
-
- /* Throw away incoming packet */
- junkpacket()
- {
- register n = 3600;
- register c;
- register b;
-
- b = Ctrlbrk; Ctrlbrk = 0;
- pstat("%sError Recovery", Outarev);
- while (--n) {
- if (cdo()) {
- prcdo(); goto done;
- }
- switch (c = readline(20)) {
- case TIMEOUT:
- goto done;
- case CAN:
- case ETX:
- if (c == readline(10)) {
- b=c; goto done;
- }
- }
- }
- done: Ctrlbrk |= b; Mcstat = 0;
- pstat("");
- }
-
-
- /*
- * Send 5 CAN's to try to get the other end to shut up
- * then 5 backspaces to edit out the CAN's
- */
- canit()
- {
- register c;
-
- junkpacket();
- for (c = 5; --c>=0; )
- sendline(CAN);
- for (c = 5; --c>=0; )
- sendline('\b');
- FLUSHMO;
- }
-
- /* Fill buf with count chars padding with ^Z for CPM */
- filbuf(buf, count)
- char *buf;
- {
- register m;
-
- #ifdef NOTDEF
- register c;
- m = count;
- while((c=getc(fin))!=EOF) {
- *buf++ =c;
- if(--m == 0)
- break;
- }
- if(m == count)
- return 0;
- else
- while(--m >= 0)
- *buf++ = 032;
- return count;
- #else
- m = read(fileno(fin), buf, count);
- if (m <= 0)
- return 0;
- while (m < count)
- buf[m++] = 032;
- return count;
- #endif
- }
-
-
- /*
- * Process incoming header
- */
- procheader(name)
- register char *name;
- {
- register char *p;
- long theirsn;
- extern char Instmsg[];
-
- /* set default parameters */
- Bytesleft = DEFBYTL; Filemode = 0666; Modtime = 0L;
-
- if (name) {
- p = name + 1 + strlen(name);
- if (*p) { /* file coming from Unix type system */
- sscanf(p, "%ld%lo%o%lo", &Bytesleft,
- &Modtime, &Filemode, &theirsn);
- #ifndef DEMO
- if (Serialn && theirsn == Serialn) {
- Instmsg[0] = 0; usage(26);
- }
- #endif
- }
- }
- }
-
- /*
- * Routines to convert to/from Unix(TM) 32 bit time code (epoch:1970).
- * Good for times 1970 to 2035 approximately, by which time we should
- * be timestamping files in microseconds since the Big Bang ...
- *
- * Original factor routine from Lynn Long
- */
-
- #define EPOCH 719542L
-
- long int factor(mm, dd, yy)
- long int mm, dd, yy;
- {
- long int raw;
-
- raw = 365 * yy + dd -1 + 31 * (mm - 1);
- if(mm < 3)
- raw += ((yy -1)/4);
- else
- raw -= (23 + 4*mm)/10L - yy/4;
- return(raw);
- }
-
- #ifdef MTIME
-
-
- struct dstruct { /* Structure filled in by msdate() */
- int year;
- char month;
- char day;
- };
- struct tsruct { /* Structure filled in by mstod() */
- char hrs;
- char mins;
- char secs;
- char csecs;
- };
-
- static dayinmo[]= { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-
- #define DAYSEC 86400L
- #define DAYPYR(y) (((y&03)) ? 365:366)
- /*
- * Unpacks Unix format time into dstruct and tsruct structures
- */
-
- unutime(ds, ts, t)
- register struct dstruct *ds;
- register struct tsruct *ts;
- long t;
- {
- register int c;
- register long days, rem, y, mo;
-
- rem = t % DAYSEC; days = t / DAYSEC;
- ts->csecs = 0;
- ts->secs = rem % 60L; rem /= 60L;
- ts->mins = rem % 60L; ts->hrs = rem/60L;
-
- for (y=1970; days>=(c=DAYPYR(y)); ++y)
- days -= c;
-
- dayinmo[1] = c==366 ? 29:28;
-
- for (mo=0; days>=(c=dayinmo[mo]); ++mo)
- days -= c;
-
- ds->day = days+1; ds->month = mo+1; ds->year = y - 1980;
- #ifdef DEBUG
- lprintf("Unutime: da %d mo %d yr %d %d:%d:%d\n",
- ds->day, ds->month, ds->year, ts->hrs, ts->mins, ts->secs);
- #endif
- }
-
-
- /*
- * Packs dstruct and tsruct structures into Unix format time
- */
-
- long
- toutime(ds, ts)
- register struct dstruct *ds;
- register struct tsruct *ts;
- {
- register long t;
-
- t = factor((long)ds->month, (long)ds->day, ds->year + 1980L);
- t -= EPOCH; t *= DAYSEC;
- t += ts->secs; t += ts->mins*60; t += ts->hrs*3600L;
- #ifdef DEBUG
- lprintf("Toutime: da %d mo %d yr %d %d:%d:%d %lo\n",
- ds->day, ds->month, ds->year, ts->hrs, ts->mins, ts->secs, t);
- #endif
- return t;
- }
-
- /*
- * Sets file s to Unix time t
- */
- sutime(s, ti)
- char *s;
- long ti;
- {
- struct dstruct ds;
- struct tsruct ts;
- register unsigned d, t;
-
- unutime(&ds, &ts, ti);
-
- d = ds.day + (ds.month << 5) + (ds.year << 9);
- t = (ts.secs >> 1) + (ts.mins << 5) + (ts.hrs << 11);
- #ifdef DEBUG
- lprintf("Sutime: d=%x t=%x", d, t);
- lprintf(" da %d mo %d yr %d %d:%d:%d\n",
- ds.day, ds.month, ds.year, ts.hrs, ts.mins, ts.secs);
- #endif
- if (Usemtime)
- utime(s, d, t);
- }
-
- /*
- * Unpack time from struct expf to tsruct and dstruct
- */
- tdexpftime(ds, ts, e)
- register struct expf *e;
- register struct dstruct *ds;
- register struct tsruct *ts;
- {
- ts->hrs = (e->exptime>>11);
- ts->mins = ((e->exptime>>5)&077);
- ts->secs = ((e->exptime&037)<<1);
- ds->month = ((e->expdate>>5)&017);
- ds->day = (e->expdate&037);
- ds->year = ((e->expdate>>9)%100);
- #ifdef DEBUG
- lprintf("TDEX.. da %d mo %d yr %d %d:%d:%d\n",
- ds->day, ds->month, ds->year, ts->hrs, ts->mins, ts->secs);
- #endif
- }
-
- #endif /* M T I M E */
-